package com.sen.app.timemail.services.impl;

import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.OutputStreamWriter;
import java.io.Writer;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.apache.commons.io.IOUtils;
import org.apache.commons.lang.ArrayUtils;
import org.apache.commons.lang.StringUtils;
import org.apache.commons.mail.DefaultAuthenticator;
import org.apache.commons.mail.EmailException;
import org.apache.commons.mail.HtmlEmail;
import org.apache.log4j.Logger;

import com.sen.app.timemail.entity.RecipientInfoEntity;
import com.sen.app.timemail.services.SendEmailService;
import com.sen.app.timemail.utils.EnvUtils;
import com.sen.app.timemail.utils.ExcelReaderUtils;
import com.sen.app.timemail.utils.FtlUtils;
import com.sen.app.timemail.utils.cfg.AppPropReader;

import freemarker.template.Template;

public class SendEmailServiceImpl implements SendEmailService {
    
	/** 日志记录器 */
	private static Logger logger = Logger.getLogger(SendEmailServiceImpl.class);
	
	/**
	 * 默认的邮箱客户名，如果邮箱客户姓和名都为空，则使用该名字
	 */
	private static final String DEFAULT_NAME = "Sir";
	
	/**
	 * 发送邮件
	 * 
	 * @param info 需要发送的信息
	 * @return 非空则发送成功，否则失败
	 */
	@SuppressWarnings({"unchecked","rawtypes"})
	public String sendTo(RecipientInfoEntity info) {
		String retVal = "";
		// 邮箱地址为空，直接跳过
		if (null == info || StringUtils.isBlank(info.getEmailAddr())) {
			return retVal;
		}
		
		HtmlEmail htmlEmail = new HtmlEmail();
		// 邮件服务器
		htmlEmail.setHostName(AppPropReader.getPropertie("send.email.hostName"));
		// 用户名密码
		htmlEmail.setAuthenticator(new DefaultAuthenticator(AppPropReader.getPropertie("send.email.userName"),
				AppPropReader.getPropertie("send.email.password")));
		
		try {
			// 发送者
			htmlEmail.setFrom(AppPropReader.getPropertie("send.email.adrress"));
		} catch (Exception e) {
			logger.info("未发送到".concat(info.getEmailAddr()).concat(",原因:设置发送者出错."));
			logger.error(e.getMessage(), e);
		}
		
		// 主题
		htmlEmail.setSubject(AppPropReader.getPropertie("emailSubject"));
		
		try {
			// 接收者
			htmlEmail.addTo(info.getEmailAddr());
		} catch (Exception e) {
			logger.warn("未发送到".concat(info.getEmailAddr()).concat(",原因:设置发送者出错."));
			logger.error(e.getMessage(), e);
			return retVal;
		}
		
		// 广告图片附件
		String adsImgCid = "";
		try {
			String imgPath = AppPropReader.getPropertie("adsImgPath");
			File adsImg = new File(imgPath);
			if (null != adsImg && adsImg.exists()) {
				adsImgCid = htmlEmail.embed(adsImg, adsImg.getName());
			}
		} catch (Exception e) {
			logger.warn("设置广告图片附件出错!");
			logger.error(e.getMessage(), e);
		}
		
		// logo图片附件
		String logoImgCid = "";
		try {
			String imgPath =  AppPropReader.getPropertie("logoImgPath");
			File logoImg = new File(imgPath);
			if (null != logoImg && logoImg.exists()) {
			    logoImgCid = htmlEmail.embed(logoImg, logoImg.getName());
			}
		} catch (Exception e) {
			logger.warn("设置logo图片附件出错!");
			logger.error(e.getMessage(), e);
		}
		
		// 模版数据，用于编译email内容
		Map datas = new HashMap();
		datas.put("firstName", StringUtils.defaultIfEmpty(info.getFirstName(), ""));
		datas.put("lastName", StringUtils.defaultIfEmpty(info.getLastName(), ""));
		datas.put("logoImgCid", logoImgCid);
		datas.put("adsImgCid", adsImgCid);
		// email 内容
		String emailContent = buildEmailContent(datas);
		try {
			htmlEmail.setHtmlMsg(emailContent);
		} catch (Exception e) {
			logger.warn("未发送到".concat(info.getEmailAddr()).concat(",原因:邮件内容为空."));
			logger.error(e.getMessage(), e);
			return retVal;
		}
		
		// 客户端不支持html邮件提示
		try {
			htmlEmail.setTextMsg("Your email client does not support HTML messages");
		} catch (EmailException e) {
			logger.warn("设置提示出错,原因:文本提示为空.");
			logger.error(e.getMessage(), e);
		}
		
		try {
			if (StringUtils.isNotBlank(emailContent)) {
			    retVal = htmlEmail.send();
			    logger.info("已发送!返回信息:".concat(retVal));
			} else {
				logger.info("未发送到".concat(info.getEmailAddr()).concat(",原因:邮件内容为空!"));
			}
		} catch (Exception e) {
			logger.error("邮件发送失败,异常信息:".concat(e.getMessage()), e);
		}
		return retVal;
	}
	
	/**
	 * 根据模板编译邮件内容
	 * @param info 邮件信息
	 * @return 邮件内容
	 */
	@SuppressWarnings("rawtypes")
	private String buildEmailContent(Map datas) {
		ByteArrayOutputStream bos = new ByteArrayOutputStream();
		Writer out = new OutputStreamWriter(bos);
		try {
			Template temp = FtlUtils.getEmailHtmlTemplate();
			temp.process(datas, out);
			out.flush();
		} catch (Exception e) {
			logger.error("根据邮件模板生成邮件内容失败,异常信息:" + e.getMessage(), e);
			return "";
		} finally {
			IOUtils.closeQuietly(out);
		}
		return bos.toString();
	}
	
	/**
	 * 获取所有接收者数据
	 *  
	 * @return 返回list集合，封装了RecipientInfoEntity对象
	 */
	public List<RecipientInfoEntity> getAllRecipientEmail() {
		List<RecipientInfoEntity> retVal = new ArrayList<RecipientInfoEntity>();
		File file = new File(AppPropReader.getPropertie("emailList"));
		if (null == file || !file.exists()) {
			return retVal;
		}
		
		ExcelReaderUtils readExcel = new ExcelReaderUtils(file);
		try {
			readExcel.open();
		} catch (IOException e) {
			logger.error("读取".concat(AppPropReader.getPropertie("emailList"))
					.concat("文件出错!原因:").concat(e.getMessage()), e);
		}
		readExcel.setSheetNum(0); // 设置读取索引为0的工作表
		
		// 总行数
		int count = readExcel.getRowCount();
		for (int i = 1; i <= count; i++) {
			String[] rows = readExcel.readExcelLine(i);
			if (ArrayUtils.isNotEmpty(rows) && rows.length >= 3 ) {
				if (StringUtils.isNotBlank(rows[2])) {
					RecipientInfoEntity bean = new RecipientInfoEntity();
					bean.setFirstName(StringUtils.defaultIfEmpty(rows[0], StringUtils.EMPTY));
					bean.setLastName(StringUtils.defaultIfEmpty(rows[1], StringUtils.EMPTY));
					// 如果姓和名都为空，使用默认名字。
					if (StringUtils.isEmpty(bean.getFirstName()) 
							&& StringUtils.isEmpty(bean.getLastName())) {
						bean.setFirstName(DEFAULT_NAME);
					}
					bean.setEmailAddr(rows[2]);
					retVal.add(bean);
				}
			}
		}
		return retVal;
	}
	
	/**
	 * 获取发送失败的接收者数据
	 * 
	 * @return 返回list集合，封装了RecipientInfoEntity对象
	 */
	public List<RecipientInfoEntity> getSendFailRecipientEmail() {
		List<RecipientInfoEntity> retVal = new ArrayList<RecipientInfoEntity>();
		File file = new File(AppPropReader.getPropertie("failEmailList"));
		if (null == file || !file.exists()) {
			return retVal;
		}
		List<String> lines = new ArrayList<String>();
		try {
			lines = IOUtils.readLines(new FileInputStream(file), "UTF-8");
		} catch (IOException e) {
			logger.error("读取".concat(AppPropReader.getPropertie("failEmailList"))
					.concat("文件出错!原因:").concat(e.getMessage()), e);
		}
		
		for (String line : lines) {
			if (StringUtils.isNotBlank(line)) {
				String[] strArr = line.split("\\" + EnvUtils.ATTR_SEPA);
				if (ArrayUtils.isNotEmpty(strArr) 
						&& strArr.length == 3 
						&& StringUtils.isNotBlank(strArr[2])) {
					RecipientInfoEntity entity = new RecipientInfoEntity();
					entity.setFirstName(StringUtils.defaultIfEmpty(strArr[0], StringUtils.EMPTY));
					entity.setLastName(StringUtils.defaultIfEmpty(strArr[1], StringUtils.EMPTY));
					entity.setEmailAddr(strArr[2]);
					retVal.add(entity);
				}
			}
		}
		
		return retVal;
	}
}
